import { Matrix4 } from "../utils/Matrix4";
import { TextrueUtil } from "../utils/TextureUtil";
import { Util } from "../utils/Util";
import { WebGLUtil } from "../utils/WebGLUtil";
import { Render } from "./Render";
import { WebglTemplateBase } from "./template/WebglTemplateBase";


/*
 * @Author: Snow
 * @Date: 2021-10-11 15:08:49
 * @Description: 
 */
export class TestSimple extends WebglTemplateBase {
    public static debug = true;
    protected override initUITools(): void {
        super.initUITools();
    }

    protected override initProgram(): void {
        this.vsSource = `
            attribute vec4 a_position;
            void main() {
                gl_Position = vec4(0,0,0,1);
                gl_PointSize = 120.0;
            }
        `;

        this.fsSource = `
            precision mediump float;

            uniform sampler2D u_texture;

            void main() {
                //gl_FragColor = vec4(1,0,0,1);
                gl_FragColor = texture2D(u_texture,gl_PointCoord.xy);
            }
        `;
        super.initProgram();
    }

    protected override initBuffers(): void {
        super.initBuffers();
        const gl = Render.GL;
        // an indexed quad
        let arrays = {
            position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], },
            texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], },
            normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], },
            indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], },
        };

        let bufferInfo = WebGLUtil.createBufferInfoFromArrays(gl, arrays);

        let cameraAngleRadians = Util.degToRad(0);
        let fieldOfViewRadians = Util.degToRad(60);
        let cameraHeight = 50;

        let uniformsThatAreTheSameForAllObjects = {
            u_lightWorldPos: [-50, 30, 100],
            u_viewInverse: Matrix4.identity([]),
            u_lightColor: [1, 1, 1, 1],
        };

        let uniformsThatAreComputedForEachObject = {
            u_worldViewProjection: Matrix4.identity([]),
            u_world: Matrix4.identity([]),
            u_worldInverseTranspose: Matrix4.identity([]),
        };

        let textures = [
            TextrueUtil.makeStripeTexture(gl, { color1: "#FFF", color2: "#CCC", }),
            TextrueUtil.makeCheckerTexture(gl, { color1: "#FFF", color2: "#CCC", }),
            TextrueUtil.makeCircleTexture(gl, { color1: "#FFF", color2: "#CCC", }),
        ];

        let objects = [];
        let numObjects = 300;
        let baseColor = Util.rand(240);
        for (var ii = 0; ii < numObjects; ++ii) {
            objects.push({
                radius: Util.rand(150),
                xRotation: Util.rand(Math.PI * 2),
                yRotation: Util.rand(Math.PI),
                materialUniforms: {
                    u_colorMult: [Util.rand(1, 2) / 2, 0.5, 1, 1],
                    u_diffuse: textures[Util.randInt(textures.length)],
                    u_specular: [1, 1, 1, 1],
                    u_shininess: Util.rand(500),
                    u_specularFactor: Util.rand(1),
                },
            });
        }

        const [minSize, maxSize] = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
        //console.log(minSize,maxSize);

        // 2x2 像素数据
        const pixels = new Uint8Array([
            0xFF, 0x00, 0x00, 0xFF,  // 红
            0x00, 0xFF, 0x00, 0xFF,  // 绿
            0x00, 0x00, 0xFF, 0xFF,  // 蓝
            0xFF, 0x00, 0xFF, 0xFF,  // 品红
        ]);
        const tex = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, tex);
        gl.texImage2D(
            gl.TEXTURE_2D,
            0,                 // 级别
            gl.RGBA,           // 内部格式
            2,                 // 宽度
            2,                 // 高度
            0,                 // 边宽
            gl.RGBA,           // 格式
            gl.UNSIGNED_BYTE,  // 数据类型
            pixels,            // 原始数据
        );
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

        let drawScene = () => {
            let time = this.ts;
            time = time * 0.1 + 5;
            WebGLUtil.resizeCanvasToMatchDisplaySize(gl);
            // Clear the canvas AND the depth buffer.
            // gl.enable(gl.SCISSOR_TEST);
            // gl.scissor(100, 100, 100, 100);
            // gl.clearColor(1,0,0,1);
            // gl.clear(gl.COLOR_BUFFER_BIT);
            // return;
            
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

            gl.useProgram(this.programInfo.program);

            // let textUniformLoc = gl.getUniformLocation(this.programInfo.program,"u_texture");
            // gl.uniform1i(textUniformLoc,0);

            gl.drawArrays(gl.POINTS, 0, 1);

            return;
            // Compute the projection matrix
            let aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
            var projectionMatrix = Matrix4.perspective(fieldOfViewRadians, aspect, 1, 2000);

            // Compute the camera's matrix using look at.
            let cameraPosition = [0, 0, 100];
            let target = [0, 0, 0];
            let up = [0, 1, 0];
            let cameraMatrix = Matrix4.lookAt(cameraPosition, target, up);
            uniformsThatAreTheSameForAllObjects.u_viewInverse = cameraMatrix;

            // Make a view matrix from the camera matrix.
            let viewMatrix = Matrix4.invert(cameraMatrix);

            let viewProjectionMatrix = Matrix4.multiply(projectionMatrix, viewMatrix);

            gl.useProgram(this.programInfo.program);

            // Setup all the needed buffers and attributes.
            WebGLUtil.setBuffersAndAttributes(gl, this.programInfo, bufferInfo);

            // Set the uniforms that are the same for all objects.
            WebGLUtil.setUniforms(this.programInfo, uniformsThatAreTheSameForAllObjects);

            // Draw objects
            objects.forEach((object) => {

                // Compute a position for this object based on the time.
                let worldMatrix = Matrix4.rotateX(object.xRotation * time);
                worldMatrix = Matrix4.multiply(worldMatrix, Matrix4.rotateY(object.yRotation * time));
                worldMatrix = Matrix4.multiply(worldMatrix, Matrix4.translation(0, 0, object.radius));
                uniformsThatAreComputedForEachObject.u_world = worldMatrix;

                // Multiply the matrices.
                uniformsThatAreComputedForEachObject.u_worldViewProjection = Matrix4.multiply(viewProjectionMatrix, worldMatrix);
                uniformsThatAreComputedForEachObject.u_worldInverseTranspose = Matrix4.transpose(Matrix4.invert(worldMatrix));

                // Set the uniforms we just computed
                WebGLUtil.setUniforms(this.programInfo, uniformsThatAreComputedForEachObject);

                // Set the uniforms that are specific to the this object.
                WebGLUtil.setUniforms(this.programInfo, object.materialUniforms);

                // Draw the geometry.
                gl.drawElements(gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0);
            });

        }
        this.draw = drawScene;
    }

    // public override draw(param?: any): void {
    //     const gl = Render.GL;

    // }
}